package com.lww.feature.test.generics;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


/**
 * User: yian
 * Date: 2017/5/7
 */
//public class ReferenceTypeTest<T extends BigDecimal> {//有界类型的正确声定义方法,声明变量的时候可以用?代替T但是
//public class ReferenceTypeTest<? extends T> {//报错
//public class ReferenceTypeTest<? extends BigDecimal> {//报错能用问号
public class test<T> {//也可以声明为test<? extends BigDecimal> q12
//public class ReferenceTypeTest<?> {//类上不能声明通配符变量


    /**
     * 该方法只能返回null因为N不能被写，只能读
     */
    public static <N extends Integer> N add(N  b){
        return b;
    }
    public   void  doTest(List<T>  list) {//
        System.out.println(list.get(0).getClass());
    }

    public   void  doTest2(List<?>  list) {//编译错误泛型必须是类型参数即，实例化类型的时候传进来的

    }
//    public static void test11(List<T>) {//静态方法不能用类上声明的
//
//    }
    public  <N extends Number> double add(N a, N b){
        double sum = 0;
        sum = a.doubleValue() + b.doubleValue();//参数声明为N类型的，此处是读所以不违反PECS原则。
        return sum;
    }
    public  <N extends T> void dotest11(N a, N b){
    }
//    public   void  doTest2(List<M>  list) {//编译错误泛型必须是类型参数，类上声明的或者方法上声明的
//
//    }

    public static <M>  void  doTest23(List<M>  list) {//23和24说明不知道类型参数的时也可以不用？
        System.out.println(list.get(0).getClass());

    }
    public static   void  doTest24(List<?>  list) {
        System.out.println(list.get(0).getClass());

    }
    public   static   void  main(String[] args) {
        List< Parent > parentList  =   new  ArrayList < Parent > ();
        parentList.add(new Parent());
        List < Child >  childList  =   new  ArrayList < Child > ();
        childList.add(new Child());
        test q = new test();//即是new的
        q.doTest(parentList);
        q.doTest(childList);
        doTest23(parentList);
        doTest23(childList);
        doTest24(parentList);
        doTest24(childList);
        // 注意这里编译错误
//        doTest(childList);


        ArrayList arrayList = new ArrayList();

        arrayList.add(new Integer(1));
//        arrayList.add()//如果不注释这里ide会提示object，说明实例化类的时候
        test<? extends BigDecimal> q12 = new test<>();//
//        ReferenceTypeTest<T extends BigDecimal> q123 = new ReferenceTypeTest<>();//不能这么声明只能用?
        test q1 = new test<Parent>();//
        q1.doTest(parentList);
        q1.doTest(childList);//q1的类型参数其实object 所以object可以协变而其他类型不可以协变
        q1.doTest(Arrays.asList(1,2));
//        ReferenceTypeTest<Parent> q3 = new ReferenceTypeTest<Child>();//不可以协变

//        ReferenceTypeTest<Parent> q2 = new ReferenceTypeTest<>();//即是new的
//        q2.doTest(parentList);
//        q2.doTest(childList);
//        q2.doTest(Arrays.asList(1,2));
    }

}
